home *** CD-ROM | disk | FTP | other *** search
- (* allocprof.sml *)
- (* Copyright 1989 by AT&T Bell Laboratories *)
- structure AllocProf =
- struct
-
- local open Access Array CPS
- structure CGoptions = System.Control.CG
-
- val ARRAYS = 0
- val ARRAYSIZE = 1
- val STRINGS = 2
- val STRINGSIZE = 3
- val REFCELLS = 4
- val REFLISTS = 5
- val CLOSURES = 6
- val CLOSURESLOTS = 11
- val CLOSUREOVFL = (CLOSURES + CLOSURESLOTS)
- val KCLOSURES = (CLOSUREOVFL + 1)
- val KCLOSURESLOTS = 11
- val KCLOSUREOVFL = (KCLOSURES + KCLOSURESLOTS)
- val CCLOSURES = (KCLOSUREOVFL + 1)
- val CCLOSURESLOTS = 11
- val CCLOSUREOVFL = (CCLOSURES + CCLOSURESLOTS)
- val LINKS = (CCLOSUREOVFL + 1)
- val LINKSLOTS = 11
- val LINKOVFL = (LINKS + LINKSLOTS)
- val SPLINKS = (LINKOVFL + 1)
- val SPLINKSLOTS = 11
- val SPLINKOVFL = (SPLINKS + SPLINKSLOTS)
- val RECORDS = (SPLINKOVFL + 1)
- val RECORDSLOTS = 11
- val RECORDOVFL = (RECORDS + RECORDSLOTS)
- val SPILLS = (RECORDOVFL + 1)
- val SPILLSLOTS = 21
- val SPILLOVFL = (SPILLS + SPILLSLOTS)
- val KNOWNCALLS = (SPILLOVFL + 1)
- val STDKCALLS = (KNOWNCALLS + 1)
- val STDCALLS = (STDKCALLS + 1)
- val CNTCALLS = (STDCALLS + 1)
- val CNTKCALLS = (CNTCALLS + 1)
- val CSCNTCALLS = (CNTKCALLS + 1)
- val CSCNTKCALLS = (CSCNTCALLS + 1)
- val ARITHOVH = (CSCNTKCALLS+1)
- val ARITHSLOTS = 5
- (* Make sure the array assigned to varptr in the runtime system is at
- least this big!! Test how big by doing an allocReset from batch. *)
- val PROFSIZE = (ARITHOVH+ARITHSLOTS)
-
- in
-
- local
- fun prof(s,i) = (* Header to increment slot s by i *)
- (fn ce => let val a1 = mkLvar() and a2 = mkLvar()
- and x = mkLvar() and n = mkLvar()
- in LOOKER(P.getvar,nil,a1,
- LOOKER(P.subscript,[VAR a1,INT s],x,
- ARITH(P.+,[VAR x,INT i],n,
- LOOKER(P.getvar,nil,a2,
- SETTER(P.unboxedupdate,[VAR a2,INT s,VAR n],ce)))))
- end)
-
- fun profSlots(base,slots,ovfl) cost =
- if cost < slots
- then prof(base+cost,1)
- else prof(base,1) o prof(ovfl,cost)
-
- val id = (fn x => x)
- in
-
- local val profLinks0 = profSlots(LINKS,LINKSLOTS,LINKOVFL) in
- fun profLinks(cost) =
- if cost=0 then id
- else profLinks0 cost
- end
-
- fun profRecLinks(l) = fold (fn (cost,h) => profLinks(cost) o h)
- l id
-
- local val profRecord0 = profSlots(RECORDS,RECORDSLOTS,RECORDOVFL) in
- fun profRecord(cost) =
- if cost=0 then id
- else profRecord0 cost
- end
-
- val profClosure = profSlots(CLOSURES,CLOSURESLOTS,CLOSUREOVFL)
-
- val profKClosure = profSlots(KCLOSURES,KCLOSURESLOTS,KCLOSUREOVFL)
-
- val profCClosure = profSlots(CCLOSURES,CCLOSURESLOTS,CCLOSUREOVFL)
-
- val profSpill = profSlots(SPILLS,SPILLSLOTS,SPILLOVFL)
-
- val profStdCall = prof(STDCALLS,1)
-
- val profStdkCall = prof(STDKCALLS,1)
-
- val profCntCall = prof(CNTCALLS,1)
-
- val profCntkCall = prof(CNTKCALLS,1)
-
- val profCSCntCall = prof(CSCNTCALLS,1)
-
- val profCSCntkCall = prof(CSCNTKCALLS,1)
-
- val profKnownCall = prof(KNOWNCALLS,1)
-
- val profRefCell = prof(REFCELLS,1)
-
- val profRefList = prof(REFLISTS,1)
-
- end (* local *)
-
-
- local
- val im = Integer.makestring
- val pr = System.Print.say
- val printf = app pr
- (* Right justify st in a string of length w. *)
- fun field (st,w) =
- if w <= String.length st then st
- else let val s = " " ^ st
- in substring(s,String.length s - w, w)
- end
-
- fun ifield(i,w) = field(im i,w)
- (* Put a decimal point at position w in string st. *)
- fun decimal(st,w) =
- let val l = String.length st - w
- val a = if (l <= 0) then "0" else substring(st,0,l)
- val st' = "0000000000" ^ st
- in a ^ "." ^ substring(st',String.length st' - w,w)
- end
- fun muldiv(i,j,k) =
- (i*j div k) handle Overflow => muldiv(i,j div 2, k div 2)
- fun decfield(n,j,k,w1,w2) =
- field(decimal(im (muldiv(n,j,k)),w1)
- handle Div => "",w2)
- (* Returns the percentage i/j to 1 decimal place in a field of width k *)
- fun percent(i,j,k) = decfield(1000,i,j,1,k)
- (* Returns the percentage i/j to 2 decimal places in a field of width k *)
- fun percent2(i,j,k) = decfield(10000,i,j,2,k)
-
- fun for(start,upto,f) =
- let fun iter(i,cum:int) = if i < upto then iter(i+1,cum + f(i)) else cum
- in iter(start,0)
- end
- fun for'(start,upto,f) =
- let fun iter(i) = if i < upto then (f(i); iter(i+1)) else ()
- in iter(start)
- end
-
- in
-
- fun print_profile_info() =
- let val profvec : int array = System.Unsafe.getvar()
- fun getprof(x) = sub(profvec,x)
- fun links(i) = getprof(LINKS+i)
- fun closures(i) = getprof(CLOSURES+i)
- fun kclosures(i) = getprof(KCLOSURES+i)
- fun cclosures(i) = getprof(CCLOSURES+i)
- fun records(i) = getprof(RECORDS+i)
- fun spills(i) = getprof(SPILLS+i)
-
- val num_calls = getprof(KNOWNCALLS)
- + getprof(STDKCALLS) + getprof(STDCALLS)
- + getprof(CNTKCALLS) + getprof(CNTCALLS)
- + getprof(CSCNTKCALLS) + getprof(CSCNTCALLS)
-
- val num_closures = for(0, CLOSURESLOTS,fn i => closures(i))
- val space_closures = for(1, CLOSURESLOTS, fn i => closures(i) * (i+1))
- val space_closures = space_closures + getprof(CLOSUREOVFL) + closures(0)
-
- val num_kclosures = for(0, KCLOSURESLOTS,fn i => kclosures(i))
- val space_kclosures = for(1, KCLOSURESLOTS, fn i => kclosures(i) * (i+1))
- val space_kclosures = space_kclosures + getprof(KCLOSUREOVFL) + kclosures(0)
-
- val num_cclosures = for(0, CCLOSURESLOTS,fn i => cclosures(i))
- val space_cclosures = for(1, CCLOSURESLOTS, fn i => cclosures(i) * (i+1))
- val space_cclosures = space_cclosures + getprof(CCLOSUREOVFL) + cclosures(0)
-
- val num_closure_accesses = for(0, LINKSLOTS, fn i => links(i))
- val num_links_traced = for(1, LINKSLOTS, fn i => links(i) * i)
- val num_links_traced = num_links_traced + getprof(LINKOVFL)
-
- val num_records = for(0, RECORDSLOTS, fn i => records(i))
- val space_records = for(1, RECORDSLOTS, fn i => records(i) * (i+1))
- val space_records = space_records + getprof(RECORDOVFL) + records(0)
-
- val num_spills = for(0, SPILLSLOTS, fn i => spills(i))
- val space_spills = for(1, SPILLSLOTS, fn i => spills(i) * (i+1))
- val space_spills = space_spills + getprof(SPILLOVFL) + spills(0)
- val total = space_closures + space_kclosures + space_cclosures
- + space_records + space_spills
- + getprof(ARRAYSIZE) + getprof(ARRAYS)
- + getprof(STRINGSIZE) + getprof(STRINGS)
- + getprof(REFCELLS) * 2
- + getprof(REFLISTS) * 2
-
- val descriptors = num_closures + num_kclosures + num_cclosures
- + num_records + num_spills
- + getprof(ARRAYS) + getprof(STRINGS)+ getprof(REFCELLS)
-
- val sgetprof = im o getprof
-
- fun printLinks() =
- if num_closure_accesses>0 then
- (for'(1, LINKSLOTS,
- fn k =>
- if links(k) > 0 then
- printf[ifield(k,4),
- ifield(links(k),13),
- percent(links(k),num_closure_accesses,12),
- "%",
- ifield(links(k) * k,12),
- percent(links(k) * k, num_links_traced, 9),
- "%\n"]
- else ());
- if links(0) > 0 then
- printf[">",
- ifield(LINKSLOTS - 1,5),
- ifield(links(0),9),
- percent(links(0),num_closure_accesses,10),
- "%",
- ifield(getprof(LINKOVFL),13),
- percent(getprof(LINKOVFL),num_links_traced,10),
- "%\n"]
- else ();
-
- printf[decfield(100,num_links_traced,num_closure_accesses,2,0),
- " links were traced per access on average.\n\n"]
- ) else printf["\n"] (* end function printLinks *)
-
- fun print1(num,name,slots,getstat,ovfl,space) =
- if num>0 then
- (printf[name,":\n"];
- for'(1, slots,
- fn k =>
- if getstat(k) > 0 then
- printf[ifield(k,6),
- ifield(getstat(k),9),
- percent(getstat(k),num,9),
- "%",
- ifield(getstat(k) * (k+1),13),
- percent(getstat(k) * (k+1), total, 10),
- "%\n"]
- else ());
- if getstat(0) > 0 then
- printf[">",
- ifield(slots - 1,5),
- ifield(getstat(0),9),
- percent(getstat(0),num,9),
- "%",
- ifield(getprof(ovfl)+getstat(0),13),
- percent(getprof(ovfl)+getstat(0),total,10),
- "%\n"]
- else ();
-
- printf["total:",
- ifield(num,9),
- ifield(space,23),
- percent(space,total,10),
- "% Average size ",
- decfield(100,space-num,num,2,0),
- "\n\n"]
- ) else if (String.length(name) > 12)
- then printf[name,": 0\n\n"]
- else printf[name,": ",
- ifield(0,13 - String.length(name)),"\n\n"]
- (* end function print1 *)
-
- fun print2(stat,size,name) =
- if getprof(stat) <> 0 then
- printf[name,
- ifield(getprof(stat),6),
- ifield(getprof(size) + getprof(stat), 23),
- percent(getprof(size) + getprof(stat),total,10),
- "% Average size ",
- decfield(100,getprof(size),getprof(stat),2,0),
- "\n"]
- else printf[name,ifield(0,6),"\n"]
-
- fun print3(stat,name) =
- if getprof(stat) <> 0 then
- printf[name,
- ifield(getprof(stat),6),
- ifield(getprof(stat) * 2, 23),
- percent(getprof(stat) * 2,total,10),
- "%\n"]
- else printf[name,ifield(0,6),"\n"]
-
- in pr "\n-------------------- ALLOCATION PROFILE --------------------\n\n";
-
- pr "\n ----- FUNCTION CALLS -----\n";
- if (num_calls > 0) then
- printf["Known functions: ",
- ifield(getprof(KNOWNCALLS),10),
- " (",
- percent(getprof(KNOWNCALLS),num_calls,4),
- "%)\n",
-
- "Escaping functions: ",
- ifield(getprof(STDCALLS),10),
- " (",
- percent(getprof(STDCALLS),num_calls,4),
- "%)\n",
-
-
- "Known escaping functions: ",
- ifield(getprof(STDKCALLS),10),
- " (",
- percent(getprof(STDKCALLS),num_calls,4),
- "%)\n",
-
- "Continuations: ",
- ifield(getprof(CNTCALLS),10),
- " (",
- percent(getprof(CNTCALLS),num_calls,4),
- "%)\n",
-
- "Known continuations: ",
- ifield(getprof(CNTKCALLS),10),
- " (",
- percent(getprof(CNTKCALLS),num_calls,4),
- "%)\n",
-
- "Callee-save continuations: ",
- ifield(getprof(CSCNTCALLS),10),
- " (",
- percent(getprof(CSCNTCALLS),num_calls,4),
- "%)\n",
-
- "Known callee-save continuations: ",
- ifield(getprof(CSCNTKCALLS),10),
- " (",
- percent(getprof(CSCNTKCALLS),num_calls,4),
- "%)\n"]
- else ();
- printf["\nTotal function calls: ",
- ifield(num_calls,10),"\n\n"];
-
-
- pr "\n ----- CLOSURE ACCESSES -----\n";
- printf["Closure elements were accessed ",
- im num_closure_accesses,
- " times through ",
- im num_links_traced,
- " links:\n",
- "Size Accesses % accesses Links % links\n"];
- printLinks();
-
- pr "\n ----- HEAP ALLOCATIONS -----\n";
- pr " (only total sizes include descriptors)\n\n";
- printf["TOTAL size ", im total];
- if (total > 0) then (
- printf["; ",
- im descriptors, " descriptors accounted for ",
- percent(descriptors,total,0), "%.\n\n"])
- else printf[".\n\n"];
-
- printf[" Size Number % total Total size % TOTAL\n\n"];
-
- print1(num_closures,"Closures for escaping functions",
- CLOSURESLOTS,closures,CLOSUREOVFL,space_closures);
- print1(num_kclosures,"Closures for known functions",
- KCLOSURESLOTS,kclosures,KCLOSUREOVFL,space_kclosures);
- print1(num_cclosures,"Closures for callee-save continuations",
- CCLOSURESLOTS,cclosures,CCLOSUREOVFL,space_cclosures);
-
- print1(num_records,"Records",RECORDSLOTS,records,
- RECORDOVFL,space_records);
- print1(num_spills,"Spills",SPILLSLOTS,spills,
- SPILLOVFL,space_spills);
-
- print2(ARRAYS,ARRAYSIZE,"Arrays: ");
- print2(STRINGS,STRINGSIZE,"Strings: ");
-
- print3(REFCELLS,"Refs: ");
- print3(REFLISTS,"Ref\n list: ")
-
-
- end (* fun print_profile_info *)
-
-
- end (* local *)
-
- fun reset() = (print "New alloc profvec, size "; print PROFSIZE; print "\n";
- System.Unsafe.setvar(array(PROFSIZE,0)))
-
-
- end (* local *)
-
-
- end (* structure AllocProf *)
-